package com.jcfk.eam.service.main;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.jcfk.common.core.utils.IdUtils;
import com.jcfk.eam.domain.dto.base.EamAssetTypeDTO;
import com.jcfk.eam.domain.dto.base.EamRepairOrderFileDTO;
import com.jcfk.eam.domain.dto.base.EamSopTypeDTO;
import com.jcfk.eam.domain.dto.main.*;
import com.jcfk.eam.domain.po.base.EamRepairOrderFile;
import com.jcfk.eam.domain.po.main.*;
import com.jcfk.eam.domain.query.main.EamInspectionPlanQuery;
import com.jcfk.eam.dao.main.EamInspectionPlanDao;
import com.jcfk.common.business.service.BaseService;
import com.jcfk.common.web.domain.DataPage;
import com.jcfk.common.web.domain.RetResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jcfk.eam.domain.query.main.EamTaskPlanEquQuery;
import com.jcfk.eam.enums.TaskPeriodUnit;
import com.jcfk.eam.service.base.EamSopStandardService;
import com.jcfk.eam.service.base.EamSopTypeService;
import com.jcfk.system.api.utils.CodeBuildUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import com.jcfk.common.core.utils.BeanUtils;
import cn.hutool.core.util.StrUtil;
import com.jcfk.common.security.utils.SecurityUtils;
import com.alibaba.druid.util.StringUtils;

import static com.jcfk.common.core.utils.BeanUtils.convertList;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

import java.util.Date;

/**
 * 巡检计划
 *
 * @author awei
 * @email 522891237@gqq.com
 * @date 2024-09-24
 */
@Service
public class EamInspectionPlanService extends BaseService<EamInspectionPlanDao, EamInspectionPlan> {

    @Autowired
    private EamTaskPlanEquService eamTaskPlanEquService;

    @Autowired
    private EamInspectionPlanTeamService eamInspectionPlanTeamService;

    @Autowired
    private EamInspectionPlanPersonService eamInspectionPlanPersonService;

    @Autowired
    private EamInspectionPlanLocationService eamInspectionPlanLocationService;

    @Autowired
    private EamPointCheckOrderService eamPointCheckOrderService;

    @Autowired
    private EamSopStandardService eamSopStandardService;

    @Autowired
    private EamInspectionTaskService eamInspectionTaskService;

    @Autowired
    private EamTaskPlanAttachService eamTaskPlanAttachService;

    /**
     * EamInspectionPlan分页查询
     *
     * @param page  分页设置
     * @param query 查询条件
     * @return 分页查询结果
     */
    public DataPage<EamInspectionPlanDTO> queryByPage(DataPage<EamInspectionPlanDTO> page, EamInspectionPlanQuery query) {
        // 分页查询
        query.setPlanNo(StringUtils.isEmpty(query.getPlanNo()) ? query.getPlanNo() : "%"+query.getPlanNo() + "%");
        query.setPlanName(StringUtils.isEmpty(query.getPlanName()) ? query.getPlanName() : "%"+query.getPlanName() + "%");
        query.setExecuteDepartmentName(StringUtils.isEmpty(query.getExecuteDepartmentName()) ? query.getExecuteDepartmentName() : "%"+query.getExecuteDepartmentName() + "%");
        query.setExecuteTeamName(StringUtils.isEmpty(query.getExecuteTeamName()) ? query.getExecuteTeamName() : "%"+query.getExecuteTeamName() + "%");
        page = this.baseMapper.queryByPage(page, query);
        return page;
    }

    /**
     * 根据条件获取单表信息列表
     *
     * @param query 查询条件
     * @return List<EamInspectionPlanDTO>
     */
    public List<EamInspectionPlanDTO> getList(EamInspectionPlanQuery query) {
        // 查询条件
        QueryWrapper<EamInspectionPlan> qw = new QueryWrapper<>();
        qw.eq(query.getAssetKind() != null, "eamInspectionPlan.asset_kind", query.getAssetKind());
        qw.eq(!StrUtil.isEmpty(query.getExecuteDepartmentId()), "eamInspectionPlan.execute_department_id", query.getExecuteDepartmentId());
        qw.like(!StrUtil.isEmpty(query.getExecuteDepartmentName()), "eamInspectionPlan.execute_department_name", query.getExecuteDepartmentName());
        qw.eq(!StrUtil.isEmpty(query.getExecuteTeamId()), "eamInspectionPlan.execute_team_id", query.getExecuteTeamId());
        qw.like(!StrUtil.isEmpty(query.getExecuteTeamName()), "eamInspectionPlan.execute_team_name", query.getExecuteTeamName());
        qw.eq(query.getTaskKind() != null, "eamSopType.task_kind", query.getTaskKind());
        qw.eq(query.getEnabled() != null, "eamInspectionPlan.enabled", query.getEnabled());
        // 查询数据
        return this.baseMapper.getList(qw);
    }

    /**
     * 获取根据关联id详情表列表
     *
     * @param query 查询条件
     * @return List<EamTaskPlanEquDTO>
     */
    public List<EamTaskPlanEquDTO> getDetails(EamInspectionPlanQuery query) {
        // 查询条件
        QueryWrapper<EamTaskPlanEqu> qw = new QueryWrapper<>();
        qw.lambda().eq(!StrUtil.isEmpty(query.getId()), EamTaskPlanEqu::getTaskPlanId, query.getId());

        // 查询数据
        List<EamTaskPlanEqu> list = eamTaskPlanEquService.list(qw);

        return convertList(list, EamTaskPlanEquDTO.class);
    }

    /**
     * 获取根据关联id详情表列表
     *
     * @param query 查询条件
     * @return List<EamTaskPlanEquDTO>
     */
    public List<EamTaskPlanEquDTO> getEquipList(EamInspectionPlanQuery query) {
        // 查询条件
        QueryWrapper<EamTaskPlanEqu> qw = new QueryWrapper<>();
        qw.lambda().eq(!StrUtil.isEmpty(query.getId()), EamTaskPlanEqu::getTaskPlanId, query.getId());

        // 查询数据
        List<EamTaskPlanEqu> list = eamTaskPlanEquService.list(qw);

        return convertList(list, EamTaskPlanEquDTO.class);
    }


    /**
     * 判断EamInspectionPlan是已经存在
     *
     * @param dto
     * @return
     */
    public RetResult<String> isValid(EamInspectionPlanDTO dto) {
        int count = queryPlanCount(dto);
        if (count > 0) {
            return RetResult.fail("计划编号已存在");
        }
        return RetResult.ok();
    }

    public Integer queryPlanCount(EamInspectionPlanDTO dto){
        Integer count=this.baseMapper.queryPlanCount(dto);

        return count;
    }

    /**
     * 插入巡检计划
     *
     * @param dto 插入对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void insert(EamInspectionPlanDTO dto) {
        // 保存
        EamInspectionPlan item = new EamInspectionPlan();
        BeanUtils.copyProperties(dto, item);
        this.setDefaultValue(item);

        super.save(item);

        // 保存明细表
        eamTaskPlanEquService.saveBatch(dto.getDetails(), item.getId());
        eamInspectionPlanTeamService.saveBatch(dto.getInspectionPlanTeams(), item.getId());
        eamInspectionPlanPersonService.saveBatch(dto.getPersons(), item.getId());
        eamInspectionPlanLocationService.saveBatch(dto.getLocations(), item.getId());

        // 保存报修单附件
        QueryWrapper<EamTaskPlanAttach> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EamTaskPlanAttach::getTaskPlanId, dto.getId());
        eamTaskPlanAttachService.remove(queryWrapper);
        List<EamTaskPlanAttach> files = new ArrayList<>();
        int fileSort=1;
        for (EamTaskPlanAttachDTO planAttach : dto.getAssetPhotos()) {
            EamTaskPlanAttach eamSopStandardImg = new EamTaskPlanAttach();
            eamSopStandardImg.setTaskPlanId(item.getId());
            eamSopStandardImg.setSort(fileSort);
            eamSopStandardImg.setUrl(planAttach.getUrl());
            eamSopStandardImg.setFileType(planAttach.getFileType());
            eamSopStandardImg.setFilename(planAttach.getFilename());
            eamSopStandardImg.setOriginalfilename(planAttach.getOriginalfilename());
            eamSopStandardImg.setPath(planAttach.getPath());
            eamTaskPlanAttachService.setDefaultValue(eamSopStandardImg);
            files.add(eamSopStandardImg);
            fileSort++;
        }
        eamTaskPlanAttachService.saveBatch(files);
    }


    /**
     * 更新巡检计划
     *
     * @param dto 更新对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(EamInspectionPlanDTO dto) {

        // 保存
        EamInspectionPlan item = new EamInspectionPlan();
        BeanUtils.copyProperties(dto, item);

        // 默认数据
        this.setDefaultValue(item);

        super.updateById(item);

        // 设置关联主键
        for (EamTaskPlanEquDTO detail : dto.getDetails()) {
            detail.setTaskPlanId(item.getId());
        }

        // 保存明细表
        eamTaskPlanEquService.saveBatch(dto.getDetails(), item.getId());
        eamInspectionPlanTeamService.saveBatch(dto.getInspectionPlanTeams(), item.getId());
        eamInspectionPlanPersonService.saveBatch(dto.getPersons(), item.getId());
        eamInspectionPlanLocationService.saveBatch(dto.getLocations(), item.getId());

        // 保存报修单附件
        QueryWrapper<EamTaskPlanAttach> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EamTaskPlanAttach::getTaskPlanId, dto.getId());
        eamTaskPlanAttachService.remove(queryWrapper);
        List<EamTaskPlanAttach> files = new ArrayList<>();
        int fileSort=1;
        for (EamTaskPlanAttachDTO planAttach : dto.getAssetPhotos()) {
            EamTaskPlanAttach eamSopStandardImg = new EamTaskPlanAttach();
            eamSopStandardImg.setTaskPlanId(item.getId());
            eamSopStandardImg.setSort(fileSort);
            eamSopStandardImg.setUrl(planAttach.getUrl());
            eamSopStandardImg.setFileType(planAttach.getFileType());
            eamSopStandardImg.setFilename(planAttach.getFilename());
            eamSopStandardImg.setOriginalfilename(planAttach.getOriginalfilename());
            eamSopStandardImg.setPath(planAttach.getPath());
            eamTaskPlanAttachService.setDefaultValue(eamSopStandardImg);
            files.add(eamSopStandardImg);
            fileSort++;
        }
        eamTaskPlanAttachService.saveBatch(files);
    }


    /**
     * 设置添加默认值
     *
     * @param item 添加对象
     */
    public void setDefaultValue(EamInspectionPlan item) {
        if (StrUtil.isEmpty(item.getCreatedUserId())) {
            item.setCreatedUserId(SecurityUtils.getUserId());
            item.setCreateTime(new Date());
            item.setVersion(1L);
            item.setCreatedUserName(SecurityUtils.getUserName());
        }
        item.setLastUpdatedUserId(SecurityUtils.getUserId());
        item.setLastUpdateTime(new Date());

        item.setLastUpdatedUserName(SecurityUtils.getUserName());
    }


    /**
     * 根据主键获取巡检计划信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public EamInspectionPlanDTO get(String id) {
        // 查询数据
        EamInspectionPlan item = this.baseMapper.selectById(id);
        EamInspectionPlanDTO dto = new EamInspectionPlanDTO();
        try {
            BeanUtils.copyProperties(item, dto);
        } catch (RuntimeException e) {
            throw e;
        }

        // 查询作业设备列表
        EamTaskPlanEquQuery equQuery=new EamTaskPlanEquQuery();
        equQuery.setTaskPlanId(id);
        List<EamTaskPlanEquDTO> list = eamTaskPlanEquService.getList(equQuery);
        dto.setDetails(list);

        // 查询作业班组
        QueryWrapper<EamInspectionPlanTeam> teamQueryWrapper = new QueryWrapper<>();
        teamQueryWrapper.lambda().eq(EamInspectionPlanTeam::getPlanId, id);
        List<EamInspectionPlanTeam> teamList = eamInspectionPlanTeamService.list(teamQueryWrapper);
        dto.setInspectionPlanTeams(convertList(teamList, EamInspectionPlanTeamDTO.class));

        // 查询作业人员
        QueryWrapper<EamInspectionPlanPerson> planPersonQueryWrapper = new QueryWrapper<>();
        planPersonQueryWrapper.lambda().eq(EamInspectionPlanPerson::getPlanId, id);
        List<EamInspectionPlanPerson> planPeople = eamInspectionPlanPersonService.list(planPersonQueryWrapper);
        dto.setPersons(convertList(planPeople, EamInspectionPlanPersonDTO.class));

        // 查询作业路线
        QueryWrapper<EamInspectionPlanLocation> planLocationQueryWrapper = new QueryWrapper<>();
        planLocationQueryWrapper.lambda().eq(EamInspectionPlanLocation::getInspectionPlanId, id);
        List<EamInspectionPlanLocation> locations = eamInspectionPlanLocationService.list(planLocationQueryWrapper);
        dto.setLocations(convertList(locations, EamInspectionPlanLocationDTO.class));

        QueryWrapper<EamTaskPlanAttach> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EamTaskPlanAttach::getTaskPlanId, dto.getId());
        List<EamTaskPlanAttach> fileList = eamTaskPlanAttachService.list(queryWrapper);
        dto.setAssetPhotos(convertList(fileList, EamTaskPlanAttachDTO.class));


        return dto;
    }

    /**
     * 根据主键获取巡检计划信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public void deleteItem(String id) {
        this.removeById(id);
    }

    /**
     * 定时生成功能
     */
    @Scheduled(cron = "0 0 23 * * ?")
    public void timedBuildOrder(){
        //获取可用计划列表
        EamInspectionPlanQuery planQuery=new EamInspectionPlanQuery();
        List<EamInspectionPlanDTO> planList=this.getList(planQuery);
        for(EamInspectionPlanDTO plan : planList){
            if(plan.getPlanStartDate().compareTo(new Date())<=0&&plan.getPlanEndDate().compareTo(new Date())>=0){
                OrderBuildRequest buildRequest=new OrderBuildRequest();
                buildRequest.setPlanId(plan.getId());
                buildRequest.setPlanWorkTime(new Date());
                this.buildOrder(buildRequest);
            }
        }
    }

    /**
     * 生成作业工单
     * @param buildRequest
     */
    @Transactional(rollbackFor = Exception.class)
    public RetResult<String> buildOrder(OrderBuildRequest buildRequest){

        Long day= DateUtil.between(new Date(),buildRequest.getPlanWorkTime(), DateUnit.DAY,false);
        if(DateUtil.between(new Date(),buildRequest.getPlanWorkTime(),DateUnit.DAY,false)<0){
            return RetResult.fail("计划点检日期不能小于当前日期");
        }

        // 记录开始时间
        Instant start = Instant.now();

        //获取作业计划
        EamInspectionPlan plan = this.baseMapper.selectById(buildRequest.getPlanId());

        //获取最后一次工单计划时间
        Date lastOrderTime=eamPointCheckOrderService.getLastOrderPlanTime(buildRequest.getPlanId());
        Integer taskPeriodHour=0;
        String taskPeriodUnitDes="";
        if(lastOrderTime!=null){
            if(plan.getTaskPeriodUnit().equals(TaskPeriodUnit.HOUR.getValue())){
                //每时
                taskPeriodHour=plan.getTaskPeriod();
            }
            if(plan.getTaskPeriodUnit().equals(TaskPeriodUnit.DAY.getValue())){
                //每日
                taskPeriodHour=plan.getTaskPeriod()*24;
            }
            if(plan.getTaskPeriodUnit().equals(TaskPeriodUnit.WEEK.getValue())){
                //每周
                taskPeriodHour=plan.getTaskPeriod()*24*7;
            }
            if(plan.getTaskPeriodUnit().equals(TaskPeriodUnit.MONTH.getValue())){
                //每月
                taskPeriodHour=plan.getTaskPeriod()*24*30;
            }
            if(plan.getTaskPeriodUnit().equals(TaskPeriodUnit.QUARTER.getValue())){
                //每季
                taskPeriodHour=plan.getTaskPeriod()*24*30*3;
            }
            if(plan.getTaskPeriodUnit().equals(TaskPeriodUnit.YEAR.getValue())){
                //每年
                taskPeriodHour=plan.getTaskPeriod()*24*363;
            }
            if(DateUtil.between(lastOrderTime,buildRequest.getPlanWorkTime(),DateUnit.HOUR)<taskPeriodHour){
                return RetResult.fail("上一次生成工单日期距离计划点检日期未超过"+plan.getTaskPeriod()+TaskPeriodUnit.fromString(plan.getTaskPeriodUnit()).getDesc()+"无需生成");
            }
        }

        //获取作业设备
        EamInspectionPlanQuery planQuery=new EamInspectionPlanQuery();
        planQuery.setId(buildRequest.getPlanId());
        List<EamTaskPlanEquDTO> taskEquList=getEquipList(planQuery);

        //创建任务
        EamInspectionTaskDTO inspectionTask=new EamInspectionTaskDTO();
        inspectionTask.setId(IdUtils.newId());
        inspectionTask.setAssetKind(plan.getAssetKind());
        inspectionTask.setSopTypeId(plan.getSopTypeId());
        inspectionTask.setInspectionPlanId(plan.getId());
        inspectionTask.setExecuteTeamName(plan.getExecuteTeamName());
        inspectionTask.setTaskNo(CodeBuildUtils.buildCode("inspectionTask",buildRequest.getTaskKind()));
        inspectionTask.setTaskName(plan.getPlanName());
        inspectionTask.setTaskStatus(0);
        inspectionTask.setInspectTotalNumber(taskEquList.size());
        inspectionTask.setNotInspectedNumber(taskEquList.size());
        inspectionTask.setExceptionNumber(0);
        inspectionTask.setPlanExecuteTime(buildRequest.getPlanWorkTime());
        eamInspectionTaskService.insert(inspectionTask);

        EamPointCheckResultDTO sopStandard=null;

        for(EamTaskPlanEquDTO planEqu : taskEquList){
            if(sopStandard==null||!planEqu.getSopStandardId().equals(sopStandard.getId())){
                sopStandard=eamSopStandardService.getSopStandard(planEqu.getSopStandardId());
            }
            OrderBuildRequest orderBuildRequest=new OrderBuildRequest();
            orderBuildRequest.setPlanId(buildRequest.getPlanId());
            EamAssetInfo eamAssetInfo=new EamAssetInfo();
            eamAssetInfo.setId(planEqu.getAssetId());
            eamAssetInfo.setAssetCode(planEqu.getAssetCode());
            eamAssetInfo.setAssetName(planEqu.getAssetName());
            //生成点检单
            orderBuildRequest.setStandardId(planEqu.getSopStandardId());
            orderBuildRequest.setStandardCode(planEqu.getSopStandardCode());
            orderBuildRequest.setPlanWorkTime(buildRequest.getPlanWorkTime());
            orderBuildRequest.setTaskKind(buildRequest.getTaskKind());
            orderBuildRequest.setAssetKind(buildRequest.getAssetKind());
            orderBuildRequest.setExecutePersonId(planEqu.getTaskPersonIds());
            orderBuildRequest.setOrderStatus(0);
            orderBuildRequest.setExecutePersonName(planEqu.getTaskPersonNames());
            orderBuildRequest.setOrderNo(CodeBuildUtils.buildCode("inspectionOrder",buildRequest.getTaskKind()));
            orderBuildRequest.setTaskId(inspectionTask.getId());

            eamPointCheckOrderService.buildOrder(orderBuildRequest,eamAssetInfo,sopStandard);
        }

        // 记录结束时间
        Instant end = Instant.now();

        // 计算耗时，打印结果
        System.out.println("耗时: " + Duration.between(start, end).toMillis() + " 毫秒");

        return RetResult.ok();
    }
}

